package com.dragon.mmochat.model.scheduleJob.pkGame.activities;

import java.awt.Color;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dragon.mmochat.MmochatConstant;
import com.dragon.mmochat.message.Mmochat_1_1S;
import com.dragon.mmochat.model.MmochatTeam;
import com.dragon.mmochat.model.battle.MmochatBattle;
import com.dragon.mmochat.model.enumType.MmochatBattleType;
import com.dragon.mmochat.model.enumType.MmochatEventType;
import com.dragon.mmochat.model.enumType.MmochatNpcFaceType;
import com.dragon.mmochat.model.enumType.MmochatNpcItemType;
import com.dragon.mmochat.model.enumType.MmochatRoleBmpType;
import com.dragon.mmochat.model.enumType.MmochatRoleStateType;
import com.dragon.mmochat.model.enumType.MmochatTeamConditionType;
import com.dragon.mmochat.model.enumType.MmochatTeamStateType;
import com.dragon.mmochat.model.gang.MmochatGang;
import com.dragon.mmochat.model.gang.MmochatGangMember;
import com.dragon.mmochat.model.map.MmochatMap;
import com.dragon.mmochat.model.map.MmochatMapTransPoint;
import com.dragon.mmochat.model.role.MmochatNpc;
import com.dragon.mmochat.model.role.MmochatPlayer;
import com.dragon.mmochat.service.MmochatBattleService;
import com.dragon.mmochat.service.MmochatChatService;
import com.dragon.mmochat.service.MmochatDao;
import com.dragon.mmochat.service.MmochatGangService;
import com.dragon.mmochat.service.MmochatMainService;
import com.dragon.mmochat.service.MmochatMapService;
import com.dragon.mmochat.service.MmochatNpcService;
import com.dragon.mmochat.service.MmochatTeamService;
import com.dragon.mmochat.util.MmochatUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

//帮派大乱斗
public class MmochatGangMixedPkGame implements MmochatPkGame {
	private static Logger log = LoggerFactory
			.getLogger(MmochatGangMixedPkGame.class);
	private static final int minGangNum = 2; // 开赛最少帮派要求
	public static int pkLine = 3; // 比赛线路，4线
	private static ScheduledFuture<?> fightHandle = null;
	private static Boolean isOver = false;
	private static Boolean awardDealed = false; // 奖励是否已经发放
	private static final int initScore = 1000; // 帮派大乱斗初始积分
	private static ScheduledExecutorService pkThreadPool = Executors
			.newScheduledThreadPool(1);
	public static Map<Integer, MmochatGang> gangs = new ConcurrentHashMap<Integer, MmochatGang>();

	public static List<String> doubleAwardDateList = new ArrayList<String>(); // 双倍奖励的时间点

	public static void addDoubleAwardDate(String date) {
		doubleAwardDateList.add(date);
	}

	public static boolean isTodayDoubleAward() {
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
		String today = sdf.format(new Date());
		if (doubleAwardDateList.contains(today)) {
			return true;
		}
		return false;
	}

	public static int getAwardParam() {
		if (isTodayDoubleAward()) {
			return 2;
		}
		return 1;
	}

	@Override
	public void prepare() {

		try {
			MmochatMap map = new MmochatMap();
			map.setMapId(MmochatConstant.mapId_gangMixedBattle);
			map.setMapDataId(MmochatConstant.mapDataId_gangFixedBattle);
			map.setCanChangeLine(false);
			map.setWalkToBattle(false);
			map.setCanFriendlyPk(false);
			map.setCanTransToFriend(false);
			map.setTeamCondition(MmochatTeamConditionType.只允许同帮派组队);
			map.setMapName("帮派大乱斗会场");

			// 增加地图传送NPC
			MmochatNpc npc = new MmochatNpc();
			npc.setNpcId(MmochatConstant.npcId_gangMixedPkNpc1);
			npc.setMapId(MmochatConstant.mapId_gangMixedBattle);
			npc.setX((short) 286);
			npc.setY((short) 284);
			npc.setName("帮派大乱斗传送人");
			npc.setBmpType(MmochatRoleBmpType.老头儿);
			npc.setFace(MmochatNpcFaceType.朝左);
			npc.getFunctionItems().add(MmochatNpcItemType.退出会场前往余杭);
			npc.getFunctionItems().add(MmochatNpcItemType.退出会场前往江宁);
			npc.getFunctionItems().add(MmochatNpcItemType.退出会场前往开封);
			map.addNpc(npc);
			MmochatNpcService.npcs.put(npc.getNpcId(), npc);

			MmochatMapService.maps.put(map.getMapId(), map);

			String sysInfo = "帮派大乱斗即将开始,请大家到江宁找"
					+ MmochatUtil.wrapColor("帮派使者", Color.yellow)
					+ "进入场地!比赛将于20:00开始!";
			if (isTodayDoubleAward()) {
				sysInfo += MmochatUtil.wrapColor("今天帮战奖励翻倍!", Color.red);
			}
			MmochatChatService.sendSystemMsg(sysInfo);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	@Override
	public void start() {
		try {
			MmochatMap map = MmochatMapService.maps
					.get(MmochatConstant.mapId_gangMixedBattle);
			if (map == null) {
				return;
			}
			isOver = false;
			awardDealed = false;
			gangs.clear();
			Map<Integer, MmochatPlayer> updateMap = new ConcurrentHashMap<Integer, MmochatPlayer>();
			for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
				if (!me.hasGang()) {
					// 没有帮派，请他离开
					kickOutFromGangMixedPkGame(me);
					updateMap.put(me.getRoleId(), me);
				} else {
					MmochatGang gang = MmochatGangService.getGangById(me
							.getGangId());
					if (gang == null) {
						kickOutFromGangMixedPkGame(me);
						updateMap.put(me.getRoleId(), me);
					} else {
						gang.setGangActivityScore(0);
						gangs.put(me.getGangId(), gang);
					}
				}
			}

			if (gangs.size() < minGangNum) {
				// 参加的帮派少于2支，比赛结束，请所有人离开
				for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
					kickOutFromGangMixedPkGame(me);
					updateMap.put(me.getRoleId(), me);
					MmochatChatService.sendSystemMsgToPerson(me,
							"本次帮派大乱斗因参加的帮派不足,无法开赛!");
					log.debug(me.getName() + "因人数不足离开帮派大乱斗.");
				}
			} else {
				// 开始比赛
				// 人数足够,设置每个玩家初始积分
				for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
					me.setCommonActivityScore(initScore);
					MmochatChatService.sendSystemMsgToPerson(me,
							"比赛即将开始，您当前体力值为" + initScore + ",当体力值为0时将无法继续比赛。");
				}

				// 开始比赛,每隔2分钟自动匹配队伍对战,直到只剩一支帮派
				fightHandle = pkThreadPool.scheduleWithFixedDelay(
						new RandomTeamFight(), 10, 100, TimeUnit.SECONDS);
			}
			// try {
			// MmochatDao.batchUpdateRoleLeavePkGame(updateMap.values());
			// } catch (Exception e) {
			// e.printStackTrace();
			// }
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Override
	public void end() {
		if (fightHandle == null) {
			return;
		}
		fightHandle.cancel(true);
		fightHandle = null;

		MmochatMap map = MmochatMapService.maps
				.get(MmochatConstant.mapId_gangMixedBattle);
		if (map == null) {
			return;
		}
		if (!isOver) {
			synchronized (isOver) {
				if (!isOver) {
					isOver = true;
				} else {
					return;
				}
			}
		}

		// 比赛结束，进行排名，发送奖励
		dealAward();

		// 将地图内的所有人转移到固定地图,并解散队伍
		Map<Integer, MmochatPlayer> updateMap = new ConcurrentHashMap<Integer, MmochatPlayer>();
		for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
			kickOutFromGangMixedPkGame(me);
			updateMap.put(me.getRoleId(), me);
		}

		MmochatMapService.maps.remove(map.getMapId());

		// try {
		// MmochatDao.batchUpdateRoleLeavePkGame(updateMap.values());
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
	}

	// 自动随机匹配战斗
	// 空闲的玩家未经系统操作不会变成战斗状态
	// 战斗状态的玩家可能在匹配过程中变成空闲状态
	class RandomTeamFight implements Runnable {

		@Override
		public void run() {
			try {
				MmochatMap map = MmochatMapService.maps
						.get(MmochatConstant.mapId_gangMixedBattle);
				if (map == null) {
					return;
				}

				if (isGangMixedPkOver()) {
					return;
				}

				List<MmochatPlayer> freePlayerList = new ArrayList<MmochatPlayer>();
				// 掉线或离开地图的玩家会自动从地图玩家中去除
				Map<Integer, MmochatPlayer> updateMap = new ConcurrentHashMap<Integer, MmochatPlayer>();
				for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
					if (!me.isInBattle() && me.getCommonActivityScore() <= 0) {
						// 积分不足，请出武道会
						kickOutFromGangMixedPkGame(me);
						updateMap.put(me.getRoleId(), me);
						MmochatChatService.sendSystemMsgToPerson(me,
								"您的比赛积分不足，被请离了会场。");
					}

					// 空闲的个人或队长
					if (me.getCommonActivityScore() > 0
							&& !me.isInBattle()
							&& MmochatTeamService.getTeamState(me) != MmochatTeamStateType.队员) {
						// 锁定状态,锁定后不能组队,不能加人,不能离图
						if (me.lockState(MmochatRoleStateType.准备进入帮派大乱斗战斗)) { // ?何时unlock,不要漏了
							freePlayerList.add(me);
						}
					}
				}
				if (freePlayerList.size() > 1) {
					// 乱序排序
					Collections.shuffle(freePlayerList);

					// 可能其中一方在此时掉线或离开游戏,但仍将以自动战斗方式参加战斗
					// 如果战斗结束时发现此人不在此地图或离线,则判断其为弃权
					for (int i = 0; i < freePlayerList.size(); i++) {
						MmochatPlayer person1 = freePlayerList.get(i);
						if (person1 == null
								|| person1.getState() != MmochatRoleStateType.准备进入帮派大乱斗战斗
								|| person1.isInBattle()) {
							continue;
						}
						// 第i个玩家要么与后面某个玩家匹配上，要么无法匹配后面所有玩家
						for (int j = i + 1; j < freePlayerList.size(); j++) {
							try {
								MmochatPlayer person2 = freePlayerList.get(j);
								if (person2 == null
										|| person2.getState() != MmochatRoleStateType.准备进入帮派大乱斗战斗
										|| person2.isInBattle()) {
									continue;
								}
								if (person1.getGangId() == person2.getGangId()) {
									continue;
								}
								// 不同帮派的2队人开打
								// 第一队人
								List<MmochatPlayer> team1 = new ArrayList<MmochatPlayer>();
								if (person1.isInTeam()) {
									MmochatTeam team = MmochatTeamService.teams
											.get(person1.getTeamId());
									if (team == null) {
										person1.leaveTeam();
										team1.add(person1);
									} else {
										for (Integer roleId : team
												.getMemberId().values()) {
											MmochatPlayer member = MmochatMainService
													.getRoleFromBuffer(roleId);
											if (member != null) {
												team1.add(member);
											}
										}
									}
								} else {
									team1.add(person1);
								}
								if (team1.size() == 0) {
									person1.unLockState();
									break;
								}

								// 第二队人
								List<MmochatPlayer> team2 = new ArrayList<MmochatPlayer>();
								if (person2.isInTeam()) {
									MmochatTeam team = MmochatTeamService.teams
											.get(person2.getTeamId());
									if (team == null) {
										person2.leaveTeam();
										team2.add(person2);
									} else {
										for (Integer roleId : team
												.getMemberId().values()) {
											MmochatPlayer member = MmochatMainService
													.getRoleFromBuffer(roleId);
											if (member != null) {
												team2.add(member);
											}
										}
									}
								} else {
									team2.add(person2);
								}
								if (team2.size() == 0) {
									person2.unLockState();
									continue;
								}

								if (team1.contains(person2)
										|| team2.contains(person1)) {
									// 同一队...应该不可能出现
									person1.unLockState();
									person2.unLockState();
									continue;
								}
								// 进入战斗
								person1.unLockState();
								person2.unLockState();
								MmochatBattle battle = MmochatBattleService
										.enterPVPBattle(map.getMapId(),
												(byte) pkLine, team1, team2,
												MmochatBattleType.帮派大乱斗);

								// 不允许逃跑
								if (battle != null) {
									battle.setCanEscape(false);
									//按1000人算，最多500队，最多250场战斗，一共是12秒
									try {
										Thread.sleep(50);
									} catch (Exception e) {
										e.printStackTrace();
									}
									break;
								}
							} catch (Exception e) {
								e.printStackTrace();
							}
						}
					}
				}
				for (MmochatPlayer me : freePlayerList) {
					if (me.getState() == MmochatRoleStateType.准备进入帮派大乱斗战斗) {
						me.unLockState();
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

	}

	public static boolean isGangMixedPkOver() {
		MmochatMap map = MmochatMapService.maps
				.get(MmochatConstant.mapId_gangMixedBattle);
		if (map == null || map.getLineRoleMap(pkLine).size() == 0 || isOver) {
			return true;
		}
		// 检测是否只剩一个帮派
		boolean ret = true;
		int gangId = -1;
		Map<Integer, MmochatPlayer> updateMap = new ConcurrentHashMap<Integer, MmochatPlayer>();
		for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
			if (!me.hasGang()) {
				// 没有帮派，请离比赛
				kickOutFromGangMixedPkGame(me);
				updateMap.put(me.getRoleId(), me);
				continue;
			}
			if (me.getCommonActivityScore() > 0) {
				if (gangId == -1) {
					// 第一个被检测的人
					gangId = me.getGangId();
				} else {
					if (me.getGangId() != gangId) {
						// 存在两个帮派.比赛继续
						ret = false;
						break;
					} else {
						continue;
					}
				}
			}
		}
		// try {
		// MmochatDao.batchUpdateRoleLeavePkGame(updateMap.values());
		// } catch (Exception e) {
		// e.printStackTrace();
		// }
		if (!ret) {
			return false;
		}

		// 改变状态
		if (!isOver) {
			synchronized (isOver) {
				if (!isOver) {
					isOver = true;
				} else {
					return true;
				}
			}

			// 场内玩家体力转化为积分
			try {
				for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
					if (!me.hasGang()) {
						continue;
					}
					if (me.getCommonActivityScore() > 0) {
						MmochatGang gang = MmochatGangMixedPkGame.gangs.get(me
								.getGangId());
						if (gang != null) {
							MmochatGangMember member = gang.getMembers().get(
									me.getRoleId());
							if (member != null) {
								int gangScore = me.getCommonActivityScore();
								gang.addGangActivityScore(gangScore);
								member.addBuildValue(gangScore / 2);
								gang.addBuildValue(gangScore / 2);
								MmochatChatService.sendSystemMsgToPerson(me,
										"场内已经没有其它帮派的对手，" + "您当前还有"
												+ me.getCommonActivityScore()
												+ "体力，全部转化为积分，" + "本帮增加"
												+ gangScore + "分!");
							}
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			// 发放奖励
			dealAward();

			// 将所有人清出场地
			updateMap.clear();
			for (MmochatPlayer me : map.getLineRoleMap(pkLine).values()) {
				kickOutFromGangMixedPkGame(me);
				updateMap.put(me.getRoleId(), me);
			}
			// try {
			// MmochatDao.batchUpdateRoleLeavePkGame(updateMap.values());
			// } catch (Exception e) {
			// e.printStackTrace();
			// }
		}

		return true;
	}

	// 将玩家请离比赛
	public static void kickOutFromGangMixedPkGame(MmochatPlayer me) {

		MmochatMapTransPoint newPos = MmochatMap.getMapWhenTempMapNotFound(me
				.getMapId());
		MmochatMap map1 = MmochatMapService.getMapByMapId(newPos
				.getTransToMapId());

		// 停止战斗
		if (me.isInBattle()) {
			MmochatBattle battle = MmochatBattleService.battles.get(me
					.getBattleId());
			if (battle != null) {
				battle.closeBattle();
			}
		}

		// 积分清0
		me.setCommonActivityScore(0);

		// 离开队伍
		if (me.isInTeam()) {
			MmochatTeam team = MmochatTeamService.teams.get(me.getTeamId());
			team.leaveTeam(me.getRoleId());
		}

		// TODO:其它处理
		if (!me.lockState(MmochatRoleStateType.切换地图时)) {
			log.debug("玩家" + me.getName() + "(skyid=" + me.getSkyId()
					+ ")当前状态为<" + me.getState().toString() + ">,无法传送");
			return;
		}

		// 停止交易
		me.stopDeal();

		// 清除周围玩家
		me.getSceenRoles().clear();

		// 清除坐标缓存器
		me.getPositionBuffer().clear();

		// 清除NPC列表
		me.getTmpNpcs().clear();

		// 从旧地图中删除玩家
		MmochatMap curMap = MmochatMapService.maps
				.get(MmochatConstant.mapId_gangMixedBattle);
		if (curMap != null) {
			curMap.delRole(me.getLine(), me);
		}

		// 设置新坐标
		me.setX(newPos.getNewMapX());
		me.setY(newPos.getNewMapY());
		me.setMapId(newPos.getTransToMapId());

		me.unLockState();

		Mmochat_1_1S pack = new Mmochat_1_1S();
		// 不使用hallState进行判断,以免终端连续上传两次请求后,终端hallState被第二次请求发送时更改
		pack.setMap(map1);
		pack.setLine((int) me.getLine());
		pack.setMe(me);
		MmochatMainService.enterGame(me, me.getUserConnInfo(), pack);
		synchronized (me) {
			// 坐标可能被其它线程修改，用同步保护
			me.setX(newPos.getNewMapX());
			me.setY(newPos.getNewMapY());
			MmochatUtil.sendCommonPack(me, pack);
		}
		log.debug("玩家" + me.getName() + "被送出帮派乱斗场");
	}

	// 发放奖励
	private static void dealAward() {
		if (awardDealed) {
			return;
		}
		synchronized (awardDealed) {
			if (awardDealed) {
				return;
			}
			awardDealed = true;
		}

		List<MmochatGang> gangList = new ArrayList<MmochatGang>(gangs.values());
		Collections.sort(gangList, new MmochatGang.mixedGangBattleScoreSort());

		int[] gangBuildAward = new int[] { 200000, 150000, 100000, 80000,
				60000, 50000, 40000, 30000, 20000, 10000 };
		int[] gangMoneyAward = new int[] { 3000000, 2000000, 1500000, 1000000,
				800000, 600000, 500000, 400000, 300000, 200000 };

		int winNum = gangBuildAward.length;
		if (winNum > gangList.size()) {
			winNum = gangList.size();
		}
		if (winNum == 0) {
			return;
		}

		List<Integer> gangIdList = new ArrayList<Integer>();
		List<String> gangNameList = new ArrayList<String>();

		String winMsg = "本次帮派大乱斗已经圆满结束，"
				+ MmochatUtil.wrapColor(gangList.get(0).getName(), Color.cyan)
				+ "获得了本次比赛的第一名。";
		winMsg = MmochatUtil.wrapColor(winMsg, Color.yellow);
		MmochatChatService.sendSystemMsg(winMsg);

		int awardParam = getAwardParam();

		for (int i = 0; i < winNum; i++) {
			MmochatGang gang = gangList.get(i);
			if (gang != null) {
				gangIdList.add(gang.getId());
				gangNameList.add(gang.getName());

				int awardBuild = awardParam * gangBuildAward[i];
				int awardMoney = awardParam * gangMoneyAward[i];
				gang.addBuildValue(awardBuild);
				gang.addMoney(awardMoney);
				MmochatGangService.sendGangSystemMsg(gang, "恭喜!本次帮派大乱斗，本帮总积分为"
						+ gang.getGangActivityScore() + "，获得了第"
						+ MmochatUtil.wrapColor((i + 1) + "", Color.green)
						+ "名，" + "得到" + awardBuild + "点建设度，" + awardMoney
						+ "文帮派资金的奖励。");
				gang.setGangActivityScore(0);
			}
		}
		for (int i = winNum; i < gangList.size(); i++) {
			MmochatGang gang = gangList.get(i);
			if (gang != null) {
				int awardBuild = awardParam * 2000;
				gang.addBuildValue(awardBuild);
				MmochatGangService.sendGangSystemMsg(gang, "本次帮派大乱斗，本帮总积分为"
						+ gang.getGangActivityScore() + ",获得了第" + (i + 1)
						+ "名，得到" + awardBuild + "点建设度。请继续努力，进入前10名即可获得丰厚奖励。");
				gang.setGangActivityScore(0);
			}
		}

		// 保存日志
		Gson gson = new Gson();
		String title = gson.toJson(gangIdList, new TypeToken<List<Integer>>() {
		}.getType());
		String content = gson.toJson(gangNameList,
				new TypeToken<List<String>>() {
				}.getType());
		try {
			MmochatDao.addEventLog(MmochatEventType.帮派大乱斗.getValue(), System
					.currentTimeMillis(), title, content);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		// 保存各帮派的建设度,帮派资金，个人贡献数据
		for (MmochatGang gang : gangList) {
			try {
				MmochatDao.updateAfterGangPkGame(gang);
				Thread.sleep(300);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// 重新加载
		MmochatNpcService.reloadEventLog();
	}
}
